package com.laicunba.service.impl;

import java.util.HashMap;
import java.util.Map;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.laicunba.event.ActivityJoinEvent;
import com.laicunba.pojo.ActivityDO;
import com.laicunba.pojo.ActivityJoinDO;
import com.laicunba.pojo.UserDO;
import com.laicunba.service.ActivityJoinService;
import com.laicunba.service.ActivityService;
import com.laicunba.service.ScriptService;
import com.laicunba.service.UserService;
import com.laicunba.service.activity.ActivityChanceService;
import com.laicunba.service.activity.ActivityConditionCheckService;
import com.laicunba.service.activity.ActivityRewardService;
import com.laicunba.util.AssertUtil;
import com.laicunba.util.StringUtil;

@Service
public class ActivityJoinServiceImpl extends BaseServiceImpl implements ActivityJoinService, ApplicationEventPublisherAware {
	@Autowired
	private UserService userService;
	@Autowired
	private ActivityService activityService;

	@Autowired
	private ScriptService scriptService;
	private Map<String, ActivityConditionCheckService> CONDITION_CHECK_SERVICE_MAP = new HashMap();

	private Map<String, ActivityChanceService> CHANCE_SERVICE_MAP = new HashMap();
	private ActivityChanceService defaultChangeService;

	private Map<String, ActivityRewardService> REWARD_SERVICE_MAP = new HashMap();

	private ApplicationEventPublisher applicationEventPublisher;

	@Autowired
	public void setActivityRewardService(ActivityRewardService[] activityRewardServiceList) {
		if (activityRewardServiceList != null) {
			for (ActivityRewardService service : activityRewardServiceList) {
				REWARD_SERVICE_MAP.put(service.getType(), service);
			}
		}
	}

	@Autowired
	public void setChanceService(ActivityChanceService[] activityChanceServiceList) {
		for (ActivityChanceService activityChanceService : activityChanceServiceList) {
			CHANCE_SERVICE_MAP.put(activityChanceService.getActivityId(), activityChanceService);
		}
		defaultChangeService = CHANCE_SERVICE_MAP.get("DEFAULT");
	}

	@Autowired
	public void setActivityConditionCheckServices(ActivityConditionCheckService[] activityConditionCheckServiceList) {
		for (ActivityConditionCheckService service : activityConditionCheckServiceList) {
			CONDITION_CHECK_SERVICE_MAP.put(service.getType(), service);
		}
	}

	@Transactional
	@Override
	public ActivityJoinDO doJoinActivity(String uid, String activityId, String subActId, String param) {
		UserDO userDO = userService.get(UserDO.class, uid);
		AssertUtil.assertNotNull(userDO, "USER_NOT_EXIST");
		ActivityDO activityDO = activityService.get(ActivityDO.class, activityId);
		AssertUtil.assertNotNull(activityDO, "ACTIVITYDO_NOT_EXIST");
		AssertUtil.assertTrue("enable".equalsIgnoreCase(activityDO.getStatus()), "ACT_NOT_ENABLE");
		JSONObject conditionsProfile = null;
		try {
			conditionsProfile = (JSONObject) new JSONParser().parse(activityDO.getConditions());
		} catch (ParseException e) {
			AssertUtil.assertFail("ACT_PROFILE_FORMAT_ERROR");
		}

		AssertUtil.assertNotNull(activityDO.getBeginTime(), "ACT_BEGIN_TIME_NOT_EXIST");
		AssertUtil.assertNotNull(activityDO.getEndTime(), "ACT_END_TIME_NOT_EXIST");

		// 时间有效?
		AssertUtil.assertTrue(System.currentTimeMillis() > activityDO.getBeginTime().getTime() && System.currentTimeMillis() < activityDO.getEndTime().getTime(), "ACT_TIME_INVALID");

		// 比对参与条件
		JSONArray conditionGroup = (JSONArray) (conditionsProfile.get(subActId));
		System.out.println(conditionGroup);
		// [{"bank_bid_amt_more":",,50000","true_name_exist":true},{"true_name_exist":true,"bank_bid_count_more":",,10"}]
		boolean conditionPassed = true;
		if (conditionGroup != null && conditionGroup.size() > 0) {
			for (int i = 0; i < conditionGroup.size(); i++) {
				JSONObject conditions = (JSONObject) conditionGroup.get(i);
				conditionPassed = true;
				for (Object key : conditions.keySet()) {
					// 一个特别的条件
					if ("true_name_exist".equalsIgnoreCase((String) key)) {
						if ((Boolean) conditions.get(key)) {
							if (StringUtil.isEmpty(userDO.getTrueName())) {
								conditionPassed = false;
							}
						} else {
							if (StringUtil.isNotEmpty(userDO.getTrueName())) {
								conditionPassed = false;
							}
						}
						continue;
					}
					if (!CONDITION_CHECK_SERVICE_MAP.containsKey(key)) {
						continue;
					}
					if (conditions.get(key) == null) {
						conditionPassed = false;
					} else if (!CONDITION_CHECK_SERVICE_MAP.get(key).check(userDO.getId(), conditions.get(key))) {
						conditionPassed = false;
					}
				}
				if (conditionPassed) {
					break;
				}
			}
		}
		AssertUtil.assertTrue(conditionPassed, "CONDITIONS_CHECK_FAIL");
		// 参与机会
		ActivityChanceService chanceService = CHANCE_SERVICE_MAP.containsKey(activityDO.getId()) ? CHANCE_SERVICE_MAP.get(activityDO.getId()) : this.defaultChangeService;
		AssertUtil.assertTrue(chanceService.hasChance(userDO, activityDO,subActId), "HAS_NO_CHANGE");

		//执行动态脚本
		scriptService.executeScript(userDO, activityDO,subActId);

		// 产生一个参加活动信号
		ActivityJoinDO joinDO = new ActivityJoinDO();
		joinDO.setActivityId(activityDO.getId());
		joinDO.setStatus("new");
		if (StringUtil.isNotEmpty(activityDO.getStatus())) {
			joinDO.setStatus(activityDO.getStatus());
		}
		joinDO.setUserId(userDO.getId());
		joinDO.setRewardReq(param);
		joinDO.setRewardType(activityDO.getRewardType());
		joinDO.setRewardResp(activityDO.getRewardResp());
		joinDO.setSummary(activityDO.getJoinSummary());
		joinDO.setSubActId(subActId);
		AssertUtil.assertTrue(create(joinDO), "CREATE_ACTIVITY_JOIN_DO_FAIL");

		// 给一个奖励
		if (REWARD_SERVICE_MAP.containsKey(joinDO.getRewardType())) {
			AssertUtil.assertTrue(REWARD_SERVICE_MAP.get(joinDO.getRewardType()).doReward(userDO, activityDO, joinDO), "REWARD_ERROR");
			joinDO = get(ActivityJoinDO.class, joinDO.getId());
		}

		ActivityJoinEvent event = new ActivityJoinEvent(joinDO);
		applicationEventPublisher.publishEvent(event);
		return joinDO;
	}
	
	
	@Transactional
	@Override
	public boolean doJoin(String uid, String activityId, String subActId, String param) { 
		AssertUtil.assertNotNull(doJoinActivity(uid, activityId, subActId, param), "FAIL");
		return true;
	}

	@Transactional
	@Override
	public boolean updateStatusSuccess(String id) {
		AssertUtil.assertTrue(updateDao.update("ACTIVITY_JOIN.updateStatusSuccess", id) == 1, "UPDATE_STATUS_FAIL");
		return true;
	}

	@Override
	public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
		this.applicationEventPublisher = applicationEventPublisher;

	}

	@Override
	public int count(String uid, String actId, String subActId) {
		Map map=new HashMap();
		map.put("uid", uid);
		map.put("actId", actId);
		map.put("subActId", subActId);
		return queryDao.selectOne("ACTIVITY_JOIN.count", map);
	}
}
